Titre

---------------------------------------- Chapitre I - Les bases ----------------------------------------

Crackme2 - partie 1

 

Cible : CrackMe2

Outils nécessaires :
OllyDbg (by Oleh Yuschuk)

 

Passons maintenant au Crackme2, disponible dans le dossier "Pack / Chapitre I / 4 - Crackme2 / CrackMe2.rar". Comme le 1er, il a été écrit en assembleur afin de simplifier le code. Ouvrez le, tapez un nom et un serial bidon, OK et on a le message d'erreur :

Crackme2        Serial incorrect

On ouvre Olly, menu File / Open (ou F3) et on sélectionne le Crackme2. Comme vu précédemment, on va chercher notre string "Serial incorrect". Clic droit dans le code, Search for / All referenced strings et là rien ne se passe ! Rien, excepté un surlignage jaune assez rapide en bas de la fenêtre de Olly :

no item

On a quand même le temps de lire "No items found" (Aucun résultat trouvé) avant que la barre d'information ne revienne à sa couleur normale et affiche de nouveau "Entry point of main module". Cela signifie qu'il n'y a aucune chaîne de caractères ASCII reconnaissable dans notre programme. Comment est-ce possible alors que l'on a le message " Serial incorrect !" qui s'affiche ? Tout simplement car lors de l'écriture du programme il a été prévu de les masquer pour éviter, par exemple, de donner des pistes aux reversers. Il existe de nombreuses techniques pour y parvenir (encodage, cryptage, chaînes dans un fichier annexe, etc). Pour vous donner un exemple simple, prenons par exemple le caractère A. Sa valeur hexadécimale dans la table ASCII est 41h. Imaginons que je stocke 140h, valeur se trouvant en dehors de la table ASCII étendue. Lors de la recherche de strings, Olly ne verra pas cette valeur comme un caractère lisible dans une chaîne et donc l'ignorera. Maintenant, lors de la création d'une string où il faut un A, je demande au programme de prendre cette valeur et de lui soustraire FFh. J'aurais donc 140h - FFh = 41h soit la valeur de mon A. En faisant le même genre de manipulation pour tous les caractères nécessaires, le tour est joué, il n'y a plus de strings visibles !

Il nous faut donc un autre moyen pour trouver où poser un BP intéressant. Pour cela, on va utiliser les APIs de Windows.

Ce sont des fonctions permettant d'exploiter Windows de façon simplifiée. Lors de l'écriture d'un programme, on fait appel aux APIs en leur passant simplement quelques paramètres pour effectuer différentes actions : accès à la base de registre, lecture/écriture de fichiers, affichage de boites de dialogue, etc. Leurs noms indiquent de façon assez explicite leurs rôles : GetWindowText, MessageBox, CreateFile, RegCreateKey, etc. Elles sont regroupées par type dans des fichiers de type DLL (Dynamic Link Library) tel que : User32.dll, Kernel32.dll, etc. Vous trouverez les différentes APIs et leurs fonctions sur la MSDN (MicroS oft Developer Network platforms) et une liste des principales dans le fichier d'aide Ollydbg.hlp fourni dans le pack (Pack / Chapitre 01 / 1 - Aide Ollydbg).

Revenons à notre crackme. Comment les APIs vont-elles pouvoir nous aider ? Dans le code, faites un clic droit, Search for / Names ou, plus rapide, utilisez le raccourci CTRL+N. Dans la nouvelle fenêtre qui s'ouvre sont listées toutes les APIs utilisées par le programme. En regardant leurs noms, on repère vite quelque chose d'intéressant : GetDlgItemTextA :

CTRL+N

C'est la fonction qui permet de récupérer du texte dans une boite de dialogue. Sélectionnez la, clic droit, Find references (ou CTRL+R) et on a encore une nouvelle fenêtre. Dans celle-ci, nous pouvons voir toutes les adresses dans notre programme où notre API est appelée :

Find reference

La troisième ligne étant l'appel direct vers la DLL, on va se concentrer sur les deux premières. En commentaires, Olly nous ajoute gentiment l'ID (IDentifiant) du contrôle dans lequel va être récupéré le texte. On peut donc vérifier dans la fenêtre windows. Lancez le programme avec F9 (ou F9) puis cliquez sur Alt+W :

List of windows

Si vous n'avez pas la même présentation que moi, faites un clic droit dans une partie vide de la fenêtre, Sort by et sélectionnez Parent. De cette manière, tous les contrôles seront rattachés à la fenêtre dont ils dépendent (fenêtre parent). On retrouve nos 2 ID (1002 et 1003) correspondants à des contrôles Edit (zone de texte) dans la fenêtre "XTX : Cracking Progressif - Crackme2". Et nous avons bien 2 zones de textes dans notre crackme : Nom et Serial. On revient dans la fenêtre References ( Alt + R) et on pose un BP avec F2 sur les deux premières lignes. On saisit un couple name/serial (Kirjo / 12345), OK et Olly breake. Un petit F8 (ou F8) et nous avons ceci :

Get name

La string récupérée par la fonction est apparue. Il s'agit ce coup-ci du nom, dans le contrôle ID1002 et on peut voir dans la pile qu'il est stocké à l'adresse 403350. F9 ( ou F9), on breake sur le 2eme BP, F8 (ou F8) pour exécuter la fonction :

Get serial

On a maintenant le serial, récupéré dans le contrôle ID1003, stocké à l'adresse 403170. Positionnez-vous dans le dump, faites un clic droit, Goto / Expression (ou CTRL + G). Dans la boîte de dialogue, saisissez dans la case "Enter address expression" l'adresse du serial : 403170 puis OK. Le dump se positionne sur l'adresse saisie :

Dump

On va utiliser un petit truc pour faciliter la lecture du code. Faites un clic sur le début du serial (31 ou le 1 dans la colonne ASCII) pour le sélectionner. Taper ":" (ou clic droit / Add label...). Dans la boite de dialogue, tapez "serial" puis OK. Avant cette petite manipulation, les lignes dans le code faisant référence à cette adresse apparaissaient comme ça :

Sans label

Dorénavant, on lira ceci :

Avec label

Au même endroit, on va maintenant poser un Break Point Memory (BPM). Ce sont des points d'arrêt que l'on peut poser sur des emplacements mémoire. On peut choisir si Olly breakera sur Read access (lecture du contenu de l'emplacement), Write access (écriture de données sur cet emplacement) ou Execution. Faites un clic droit sur le 31, Breakpoint / Memory ..., puis dans la boite de dialogue cochez Read Access. Chaque fois que le serial sera lu, Olly breakera et on pourra regarder ce que le programme en fait (comparaison avec le bon serial par exemple ...). On relance avec F9 ( ou F9) et on breake ici :

Kernel

Ici, nous sommes dans le module KERNELBASE, aucun intérêt pour nous. Encore F9 (ou F9) et cette fois ci on revient dans notre programme :

Modification du serial

En traçant avec F8 (ou F8) on analyse facilement ce qui se passe dans cette boucle (voir les commentaires). A la fin de celle-ci, on voit dans le dump notre serial modifié mais ce n'est donc pas ici qu'il est comparé. Notre BPM étant toujours actif et le serial modifié étant à la place du serial original, on continue avec F9 (ou F9). Olly breake à nouveau :

2nd break

Voilà un endroit beaucoup plus intéressant ! Première chose que l'on remarque, c'est que l'adresse de notre serial modifié est chargée dans ESI (1). On analyse ensuite en traçant avec F8 (ou F8) la boucle qui suit (2). On voit que notre serial modifié est comparé à la string dont l'adresse est indiquée par EDI (3), soit "JBFE" et si la comparaison n'est pas bonne, on sort de la boucle. Solution la plus simple : on remplace le JNE par des NOPs comme on l'avait fait pour le crackme précédent. Solution plus élégante : on essaye de trouver le bon serial à saisir. C'est ici relativement simple.

On a vu que le serial était modifié par un simple XOR 0Fh sur chaque caractère. Cette opération marchant dans les 2 sens (si 45h XOR 0Fh = 4A h alors 4Ah XOR 0Fh = 45h), il suffit de l'appliquer sur les caractères du bon serial pour trouver celui à saisir. Il suffit de regarder dans le dump (4) pour avoir les valeurs ASCII de chaque caractère ce qui nous donne :

Saisissez notre nouveau couple name/serial ("Kirjo" / "EMIJ"), OK et :

Bravo

Voilà, on a utilisé deux techniques : le patching et le fishing. Mais il existe une 3eme solution ...

 

Precedent        Sommaire        Suivant